#!/usr/bin/env python3
# Created by han on 2016/7/4
import os, sys, json, hashlib, subprocess
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from conf import db_conf


def color_msg(color, text, width, fill=" "):
    """
    格式化，可以定义颜色，文字的位置
    :param color: 文字颜色
    :param text: 文字内容
    :param width: 文字位置
    :param fill: 文字填充 default=" "
    :return:
    """
    msg = "\033[31;{0:d}m {1} \033[33;0m".format(color, text)
    text_msg = msg.center(width, fill)
    print(text_msg)


def file_processing(action, db_base, user_info=None):
    """
    读取或者创建用户文件
    :param action:
    :param db_base:
    :param user_info:
    :return: 如果是存储，就返回真，如果是读取，就返回用户信息
    """
    if action == "w":
        with open(db_base, "w", encoding="utf8") as user_file:
            json.dump(user_info, user_file)
            msg = "register succeed"
            color_msg(32, msg, 40)
            return True
    elif action == "r":
        with open(db_base, "r", encoding="utf8") as user_file:
            info = json.load(user_file)
            return info


def file_content(action,file):
    """
    读取传输文件内容
    :param action: 读取的动作，是rb 还是ab
    :param file:
    :return:
    """
    with open(file, action) as f:
        return f



def login():
    """
    用户登陆，登陆成功将用户信息传递给服务器
    :return: 返回用户信息
    """
    user_name = input("user或按[b]退出: ")
    if not user_name:
        return False
    db_base = db_conf.db_exit(user_name)        #用户是否存在
    if not os.path.exists(db_base):             #不存在
        msg = "please register"
        color_msg(33, msg, 40)
        return "reg"
    user_pass = input("passwd: ")           #存在输入用户名
    local_info = file_processing("r", db_base)
    user_size = local_info["user_size"]
    info = {"action": "login", "name": user_name, "passwd": user_pass, "user_size": user_size}   #生成传给服务器的用户信息
    return info



def register():
    """
    生成注册信息
    :return: (send to server user message,cliend save user message)
    """
    user_name = input("user_name: ")
    db_base = db_conf.db_exit(user_name)
    if os.path.exists(db_base):
        msg = "user_name exist"
        color_msg(33, msg, 40)
        return False
    else:
        user_pass = input("password: ")
    while True:
        user_size = input("Disk Space: (M) ")
        if not user_size.isdigit() or int(user_size) > 1024:   #如果用户输入的不是数字或者大于1024了就报错重写
            msg = "Type error or Size more than 1024M"
            color_msg(31, msg, 40)
            continue
        else:
            break
    client_dict = {"action": "register", "name":user_name, "passwd": user_pass, "user_size": user_size}  #将用户的信息写成字典
    user_info = {"action": "register", "name":user_name, "user_size": user_size}
    client_info = json.dumps(client_dict)                                   #获取序列化的后的结果
    return client_info, user_info


def user_chose(*menu):
    for i in enumerate(menu):
        print(i[0]+1,i[1])
    chose = input("请输入您的选择或按【b】退出: ")
    if chose == "b":
        return "b"
    elif chose.isdigit() and int(chose) <= len(menu):
        return chose
    else:
        msg = "type error"
        color_msg(31, msg, 40)
        return False


def get_file_md5(filename):
    if not os.path.isfile(filename):
        return
    myhash = hashlib.md5()
    with open(filename, "rb") as file:
        while True:
            b = file.read(8096)
            if not b:
                break
            myhash.update(b)
    return myhash.hexdigest()


def dir_size(path):
    """
    获取目录的大小
    :param path:
    :return:
    """
    a = os.walk(path)
    size = 0
    for root, dirs, files in a:
        size += sum([os.path.getsize(os.path.join(root, name)) for name in files])
    return size


def save_file(socket_obj, server_size, client_size, abs_filename, open_type, server_md5):
    recv_size = client_size
    # print(recv_size)
    with open(abs_filename, open_type) as local_file:
        # local_file.seek(seek_num)
        while recv_size < server_size:
            server_data = socket_obj.recv(4096)
            local_file.write(server_data)
            recv_size += len(server_data)
            view_bar(recv_size, server_size)
    client_md5 = get_file_md5(abs_filename)
    if client_md5 == server_md5:
        msg = "upload file success"
        color_msg(32, msg, 40)
    else:
        msg = "upload file incomplete"
        color_msg(31, msg, 40)


def view_bar(num,total):
    rate = num/total
    rate_num = int(rate * 100)
    r1 ='\r%s>%d%%'%("="*rate_num, rate_num)
    # r1 ='\r>%d%%'% rate_num
    sys.stdout.write(r1)
    sys.stdout.flush()


def send_file(socket_obj, confirm_data, file, file_size):
    position = confirm_data["seek"]  # 获取终端文件的位置
    send_size = confirm_data["server_size"]
    with open(file, "rb") as file_info:
        file_info.seek(position)  # 将指针移到终端位置
        for i in file_info:  # 循环遍历这个文件
            socket_obj.sendall(i)  # 开始传输
            send_size += len(i)  # 将每次传输的长度增加
            view_bar(send_size, file_size)
    return send_size


def save_info(user_dict):
    """
    保存用户信息和创建用户家目录
    :param user_dict: 用户本地保存的信息
    :return:
    """
    user_name = user_dict["name"]
    user_size = user_dict["user_size"]
    db_base = db_conf.db_exit(user_name)
    with open(db_base, "w", encoding="utf8") as user_file:                    #修改，先不在本地保存，服务器端先操作，然后拿到返回值再存本地
        json.dump(user_dict, user_file)                                        #序列化到文件中去
    abs_filename = "..\\space\\%s_%s"%(user_name, user_size)
    os.mkdir(abs_filename)
